#include "link_list.h"

// 单链表的创建
Link_list *init_link_list(void)
{
    // 1 创建 头节点的动态空间
    Link_list *list = (Link_list *)malloc(sizeof(Link_list));
    if (NULL == list)
    {
        printf("创建失败\n");
        return NULL;
    }

    list->next = NULL;  // 初始化头结点指针域为 NULL

    return list;
}

// 单链表的销毁
void free_link_list(Link_list **list)
{ 
    // 1 判断链表是否为空
    if (NULL == *list)
    {
        printf("链表 为 NULL\n");
        return;
    }
    // 2 判断链表是否只有一个结点 如果只有一个结点 直接释放头结点
    if(NULL == (*list)->next)
    {
        free(*list);
        *list = NULL;
        return;
    }
    // 3 销毁结点
    Node *ptr_1 = (*list)->next;  // 指向第一个结点
    Node *ptr_2 = ptr_1->next;    // 指向第二个结点
    for (size_t i = 0; ptr_1 != NULL; i++)
    {
        free(ptr_1);
        // if 判断  判断 ptr2 = NULL 的时候 我们如何处理
        ptr_1 = ptr_2;
        if (NULL != ptr_2)
        {
            ptr_2 = ptr_2->next;
        }
    }
    // 4 销毁头结点
    free(*list);
    *list = NULL;
}

void print_link_list(Link_list *list)
{
    if (NULL == list)
    {
        printf("链表为空\n");
        return;
    }
    if (list->next == NULL)
    {
        printf("链表无数据\n");
        return;
    }
    Node *ptr = list->next; // 指向第一个节点
    while (ptr != NULL)
    {
        printf("姓名:%s 性别:%s 年龄:%d 成绩:%d 学号:%d\n",
               ptr->data.name, ptr->data.sex, ptr->data.age,
               ptr->data.sco, ptr->data.id);
        ptr = ptr->next;
    }
    printf("\n");
}
// 单链表的插入
void tail_insert_link_list(Link_list *list, Elenemt_data data)
{
    // 创建动态空间给结点
    Node *new_node = (Node *)malloc(sizeof(Node)); // 创建结点
    if (new_node == NULL)
    {
        fprintf(stderr, "Memory allocation failed\n");
        return; // 处理内存分配失败的情况
    }
    new_node->data = data;
    new_node->next = NULL; // 新节点的下一个指针初始化为 NULL

    // 如果链表为空，直接将新节点设置为头节点
    if (list->next == NULL)
    {
        list->next = new_node;
    }
    else
    {
        Node *ptr = list->next;
        while (ptr->next != NULL)
        {
            ptr = ptr->next;
        }
        ptr->next = new_node; // 将结点链接到尾节点
    }
}

// 单链表的插入
void insert_node(Link_list *list, Elenemt_data data, int pos)
{
    if (NULL == list)
    {
        printf("链表为空\n");
        return;
    }
    Node *newnode = (Node *)malloc(sizeof(Node));
    if (NULL == newnode)
    {
        printf("创建失败\n");
        return;
    }
    newnode->data = data;
    newnode->next = NULL;
    if (1 == pos)
    {
        newnode->next = list->next;
        list->next = newnode;
        return;
    }
    Node *ptr = list->next;
    for (size_t i = 1; i < pos - 1 && NULL != ptr; i++)
    {
        ptr = ptr->next;
    }
    if (NULL == ptr)
    {
        printf("插入位置有误\n");
        free(newnode);
        return;
    }
    newnode->next = ptr->next;
    ptr->next = newnode;
    return;
}
// 单链表的删除
void tail_delete_link_list(Link_list *list)
{
    if (list == NULL || list->next == NULL)
    {
        // 如果链表为空或链表只有一个节点，直接返回
        return;
    }

    Node *prev = NULL;
    Node *current = list->next;

    // 遍历链表，找到倒数第二个节点
    while (current->next != NULL)
    {
        prev = current;
        current = current->next;
    }

    // 如果链表只有一个节点
    if (prev == NULL)
    {
        free(current);
        list->next = NULL;
    }
    else
    {
        // 删除最后一个节点
        free(current);
        prev->next = NULL;
    }
}
// 单链表的删除
void delete_node(Link_list *list, int pos)
{
    if (NULL == list)
    {
        printf("链表为空\n");
        return;
    }
    if (NULL == list->next)
    {
        printf("链表无数据\n");
        return;
    }
    Node *ptr_1 = list->next;
    Node *ptr_2 = NULL;
    if (1 == pos)
    {
        ptr_2 = ptr_1->next;
        list->next = ptr_2;
        free(ptr_1);
        return;
    }
    for (size_t i = 1; i < pos - 1 && NULL != ptr_1; i++)
    {
        ptr_1 = ptr_1->next;
    }
    if (NULL == ptr_1)
    {
        printf("删除位置有误\n");
        return;
    }
    ptr_2 = ptr_1->next;
    ptr_1->next = ptr_2->next;
    free(ptr_2);
    return;
}

// 单链表的查找
Node *find_node_id(Link_list *list, int pos)
{
    if (NULL == list)
    {
        printf("链表为空\n");
        return NULL;
    }
    if (NULL == list->next)
    {
        printf("链表无数据\n");
        return NULL;
    }
    Node *ptr = list->next;
    for (size_t i = 1; i < pos - 1 && NULL != ptr; i++)
    {
        ptr = ptr->next;
    }
    if (NULL == ptr)
    {
        printf("查找位置有误\n");
        return NULL;
    }
    return ptr;
}

Node *find_node_name(Link_list *list, char *name)
{
    if (NULL == list)
    {
        printf("链表为空\n");
        return NULL;
    }
    if (NULL == list->next)
    {
        printf("链表无数据\n");
        return NULL;
    }
    Node *ptr = list->next;
    while (NULL != ptr)
    {
        if (0 == strcmp(ptr->data.name, name))
        {
            return ptr;
        }
        // 向后遍历
        ptr = ptr->next;
    }
    return NULL;
}

// 单链表的清空
void clear_link_list(Link_list *list)
{
    if (NULL == list)
    {
        printf("链表为空\n");
        return;
    }
    if (NULL == list->next)
    {
        printf("链表无数据\n");
        return;
    }
    Node *ptr = list->next;
    Node *ptr_1 = ptr->next;
    while (NULL != ptr)
    {
        free(ptr);
        ptr = ptr_1;
        if (NULL != ptr_1)
        {
            ptr_1 = ptr_1->next;
        }
    }
    list->next = NULL;
    printf("链表已清空\n");
}

// 单链表的合并
Link_list *merge_link_lists(Link_list *list1, Link_list *list2)
{
    //1 判断链表是否为空
    if (NULL == list1 || NULL == list2)
    {
        printf("链表为空\n");
        return NULL;
    }
    //2 判断链表是否有数据
    if (NULL == list1->next && NULL == list2->next)
    {
        printf("链表都无数据\n");
        return NULL;
    }
    //3 合并链表
    Link_list *list3 = init_link_list(); //创建新链表
    Node *ptr_1 = list1->next;  //获取第一个链表的头节点
    size_t i = 0;
    for (i = 1; NULL != ptr_1; i++)  //遍历第一个链表  将第一个链表的数据插入到新链表中
    {
        insert_node(list3, ptr_1->data, i);  
        ptr_1 = ptr_1->next;  //向后遍历
    }
    ptr_1 = list2->next;  //获取第二个链表的头节点
    for (; NULL != ptr_1; i++)   //遍历第二个链表  将第二个链表的数据插入到新链表中
    {
        insert_node(list3, ptr_1->data, i);
        ptr_1 = ptr_1->next;
    }
    return list3;
}
